﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace MyVideoViewerLibrary.EAXMovies
{
    public class EAXBusiness : MyVideoViewerLibrary.IMoviesBusiness
    {
        private List<Movie> movies;
        private List<Genre> genres;

        public EAXBusiness()
        {
            genres = new List<Genre>();
            movies = new List<Movie>();

            LoadMovies();
        }

        public void LoadMovies()
        {
            if (!File.Exists(Settings.Default.EaxMovieCatalogFile))
                throw new Exception("File does not exist.");

            XDocument doc = XDocument.Load(Settings.Default.EaxMovieCatalogFile);

            int tempInt;
            decimal tempDec;
            DateTime tempDate;

            foreach (XElement xmovie in doc.Descendants("Movie"))
            {
                Movie movie = new Movie()
                    {
                        Title = xmovie.Attribute("OriginalTitle") != null ? xmovie.Attribute("OriginalTitle").Value : "",
                        SortTitle = xmovie.Attribute("FormattedTitle") != null ? xmovie.Attribute("FormattedTitle").Value : "",
                        Description = xmovie.Attribute("PlotOriginal") != null ? xmovie.Attribute("PlotOriginal").Value : "",
                        PosterImageLocation = xmovie.Attribute("Picture") != null ? xmovie.Attribute("Picture").Value : "",
                        IMDBId = xmovie.Attribute("Website") != null && xmovie.Attribute("Website").Value.Contains("imdb") ? Path.GetFileName(xmovie.Attribute("Website").Value) : ""
                    };

               
                if (xmovie.Attribute("RunningTime") != null)
                {
                    if (int.TryParse(xmovie.Attribute("RunningTime").Value, out tempInt))
                        movie.Runtime = tempInt;
                }

                if (xmovie.Attribute("EntryDate") != null)
                {
                    if (DateTime.TryParse(xmovie.Attribute("EntryDate").Value, out tempDate))
                        movie.DateAdded = tempDate;
                }

                if (xmovie.Attribute("PersonelRating") != null)
                {
                    if (decimal.TryParse(xmovie.Attribute("PersonelRating").Value, out tempDec))
                        movie.Rating = tempDec;
                }

                if (movie.Rating == 0 && xmovie.Attribute("Rating") != null)
                {
                    if (decimal.TryParse(xmovie.Attribute("Rating").Value, out tempDec))
                        movie.Rating = tempDec;
                }

                

                if (xmovie.Attribute("Links") != null)
                {
                    string[] links = xmovie.Attribute("Links").Value.Split('|');
                    string background = links.Where(l => l.EndsWith("background")).FirstOrDefault();
                    if (string.IsNullOrEmpty(background))
                        movie.BackgroundImageLocation = background;
                }

                

                if (string.IsNullOrEmpty(movie.BackgroundImageLocation) || !File.Exists(movie.BackgroundImageLocation))
                {
                    XElement thumbnail = xmovie.Descendants("Thumbnail").Where(x => x.Attribute("ThumbInfotext").Value == "Background" && x.Attribute("ThumbPath") != null && !string.IsNullOrEmpty(x.Attribute("ThumbPath").Value)).FirstOrDefault();
                    if (thumbnail != null)
                        movie.BackgroundImageLocation = thumbnail.Attribute("ThumbPath").Value;
                }

                if ((string.IsNullOrEmpty(movie.BackgroundImageLocation) || !File.Exists(movie.BackgroundImageLocation)) && !string.IsNullOrEmpty(movie.PosterImageLocation))
                {
                    movie.BackgroundImageLocation = movie.PosterImageLocation.Insert(movie.PosterImageLocation.Length - 4, "_background");
                }

                if (string.IsNullOrEmpty(movie.BackgroundImageLocation))
                {
                    XElement disc = xmovie.Descendants("Disc").FirstOrDefault();
                    if (disc != null && disc.Attribute("VideoFullPath") != null && !string.IsNullOrEmpty(disc.Attribute("VideoFullPath").Value))
                    {
                        FileInfo fi = new FileInfo(disc.Attribute("VideoFullPath").Value);
                        string background = Path.Combine(fi.DirectoryName, "background.jpg");
                        movie.BackgroundImageLocation = background;
                    }
                }

                if (xmovie.Attribute("ReleaseDate") != null)
                {
                    string temp = xmovie.Attribute("ReleaseDate").Value;
                    temp = Regex.Replace(temp, "\\(.*\\)", "");
                    if (DateTime.TryParse(temp, out tempDate))
                        movie.ReleaseDate = tempDate;

                }

                if (xmovie.Attribute("Genre") != null)
                {
                    string[] temp = xmovie.Attribute("Genre").Value.Split('|');
                    foreach (string genreString in temp)
                    {
                        Genre genre = genres.SingleOrDefault(g => g.GenreDesc == genreString.Trim());
                        if (genre == null)
                        {
                            genre = new Genre() { GenreDesc = genreString.Trim(), Movies = new List<Movie>() };
                            genres.Add(genre);
                        }
                        movie.Genres.Add(genre);
                        genre.Movies.Add(movie);
                    }
                }

                if (xmovie.Attribute("Cast") != null)
                {
                    string[] temp = xmovie.Attribute("Cast").Value.Split(',');
                    foreach (string castString in temp)
                    {
                        Match match = Regex.Match(castString, " ?([^(]*) ?\\(as ([^)]*)\\)", RegexOptions.IgnoreCase);
                        if (match.Groups.Count == 3)
                        {
                            CastMember castMember = new CastMember() { Name = match.Groups[1].Value, Role = match.Groups[2].Value };
                            movie.Cast.Add(castMember);
                        }
                    }
                }                

                movie.OnGetFiles += new GetFilesEvent(movie_OnGetFiles);

                movie.Data = xmovie;
                movies.Add(movie);
            }
        }

        void movie_OnGetFiles(Movie movie)
        {
            XElement xmovie = movie.Data as XElement;
            if (xmovie == null)
                return;
            foreach (XElement disc in xmovie.Descendants("Disc"))
            {
                if (disc != null && disc.Attribute("VideoFullPath") != null && !string.IsNullOrEmpty(disc.Attribute("VideoFullPath").Value))
                {
                    if (Path.GetFileNameWithoutExtension(disc.Attribute("VideoFullPath").Value) == "trailer")
                        movie.Trailer = disc.Attribute("VideoFullPath").Value;
                    else
                        movie.Files.Add(disc.Attribute("VideoFullPath").Value);
                }
            }
        }

        #region IMoviesBusiness Members

        public List<Movie> GetMovies()
        {
            return movies;
        }

        public List<CommandItem> GetFilterItems()
        {
            List<CommandItem> filters = new List<CommandItem>();
            filters.Add(new CommandItem("Title", (int)FilterType.Title));
            filters.Add(new CommandItem("Last Added", (int)FilterType.LastAdded));
            filters.Add(new CommandItem("Rating", (int)FilterType.Rating));
            filters.Add(new CommandItem("Genre", (int)FilterType.Genre));
            filters.Add(new CommandItem("Release Date", (int)FilterType.ReleaseDate));
            filters.Add(new CommandItem("Runtime", (int)FilterType.Runtime));
            return filters;
        }

        public List<CommandItem> GetCommandItems()
        {
            List<CommandItem> commandItems = new List<CommandItem>();
            commandItems.Add(new CommandItem("All Titles", 0));
            commandItems.Add(new CommandItem("Genres", 1));
            commandItems.Add(new CommandItem("Ratings", 2));
            return commandItems;
        }

        public List<CommandItem> GetCommandItems(int id)
        {
            List<CommandItem> commandItems = new List<CommandItem>();
            
            switch (id)
            {
                case 1:
                    foreach(Genre genre in genres.OrderBy(g=>g.GenreDesc))
                    {
                        commandItems.Add(new CommandItem(string.Format("{0} ({1})", genre.GenreDesc, genre.Movies.Count), genre));
                    }
                    break;
                case 2:
                    var q = movies.GroupBy(m => m.Rating);
                    foreach (var r in q)
                    {
                        commandItems.Add(new CommandItem(string.Format("{0} ({1})", r.Key, r.Count()), r.ToList()));
                    }
                    break;
                default:
                    break;
            }
            return commandItems;
        }

        public List<Movie> GetMoviesFromCommand(int commandId, object data)
        {

            switch (commandId)
            {
                case 0:
                    return movies;
                case 1:
                    Genre genre = data as Genre;
                    return genre.Movies;
                case 2:
                    return data as List<Movie>;
            }
            return new List<Movie>();
        }

        public bool SupportsWatched()
        {
            return false;
        }

        #endregion
    }
}
